<script setup lang="ts">
import dayjs from 'dayjs'
import { useIndicatorDataCurve, getDefaultTimes } from './composable'
import { useChartToolboxDataView } from '@/mixins/MixinChartToolboxDataView'
import { STORAGE_MODES } from '@/enum/modules/indicator'
import { STORAGE_MODES_OPTIONS } from '@/mixins/StatisticalIndicators/MixinStatisticalIndicators'
import type { DatePickType } from 'element-plus'
import UpdateDataModal from './UpdateDataModal.vue'
import { useChartTooltipTheme } from '@/mixins/MixinChartTooltipTheme'
import { DEFAULT_OPTION } from '@/components/view-chart-line/index'

const props = withDefaults(defineProps<{
  indicatorNumber: string
  title?: string
  initialTimeType?: STORAGE_MODES
  initialStartTime?: string
  initialEndTime?: string
  showYoyOrMom?: boolean
}>(), {
  title: '实时数据折线图',
  initialTimeType: STORAGE_MODES.NOW,
  initialStartTime: dayjs().subtract(24, 'hour').format('YYYY-MM-DD HH:mm'),
  initialEndTime: dayjs().format('YYYY-MM-DD HH:mm'),
  showYoyOrMom: true,
})

const emits = defineEmits<{
  (e: 'close'): void
}>()

const [visible, setVisible] = useState(false)

const showYoy = ref(false)
const showMom = ref(false)

const updateDataModalRef = ref<InstanceType<typeof UpdateDataModal>>()

const timeTypeOptions = computed(() => {
  return STORAGE_MODES_OPTIONS.filter(v => v.value !== STORAGE_MODES.NOW)
})
const timeType = ref(props.initialTimeType)
const startTime = ref(props.initialStartTime)
const endTime = ref(props.initialEndTime)

const startCacheTime = ref('')
const endCacheTime = ref('')

const isLive = computed(() => unref(timeType) === STORAGE_MODES.NOW)
const isHour = computed(() => unref(timeType) === STORAGE_MODES.HOUR)
const pickerType = computed(() => {
  return ({
    [STORAGE_MODES.NOW]: 'datetime',
    [STORAGE_MODES.FIFTEEN_MINUTES]: 'datetime',
    [STORAGE_MODES.HOUR]: 'datetime',
    [STORAGE_MODES.DAY]: 'date',
    [STORAGE_MODES.MONTH]: 'month',
    [STORAGE_MODES.YEAR]: 'year',
  })[timeType.value] as DatePickType
})
const pickerFormat = computed(() => {
  return ({
    [STORAGE_MODES.NOW]: 'YYYY-MM-DD HH:mm',
    [STORAGE_MODES.FIFTEEN_MINUTES]: 'YYYY-MM-DD HH:mm',
    [STORAGE_MODES.HOUR]: 'YYYY-MM-DD HH',
    [STORAGE_MODES.DAY]: 'YYYY-MM-DD',
    [STORAGE_MODES.MONTH]: 'YYYY-MM',
    [STORAGE_MODES.YEAR]: 'YYYY',
  })[timeType.value]
})

const {
  loading,
  data,
  yoyData,
  momData,
  indicator,
  queryIndicatorDataByTimeType,
} = useIndicatorDataCurve()

const { dataView } = useChartToolboxDataView({
  optionToContent: (opt: any, g: (d: any) => string | HTMLElement) => {
    const series = opt.series ?? []
    const times = opt.xAxis[0]?.data ?? []
    const values = []
    for (const i in times) {
      const vv = []
      for (const j in series) {
        vv.push(series[j].data[i])
      }
      values.push([times[i], ...vv])
    }

    const data = [
      ['时间', ...series.map((v: any) => v.name)],
      ...values,
    ]
    return g(data)
  },
  dataViewFirstCellName: '时间',
})
const tooltipTheme = useChartTooltipTheme()
const lineData = computed(() => unref(data))
const yoyLineData = computed(() => unref(yoyData))
const momLineData = computed(() => unref(momData))
const dataset = computed(() => {
  const t = { source: lineData.value, name: '本期' }
  const ret = [t]
  if (showYoy.value) {
    ret.push({ source: yoyLineData.value, name: '同比' })
  }
  if (showMom.value) {
    ret.push({ source: momLineData.value, name: '环比' })
  }
  return ret
})
const series = computed(() => {
  const ret: any[] = []
  for (const item of unref(dataset)) {
    ret.push({
      type: 'line',
      name: item.name,
      data: item.source[1] ? item.source[1].slice(1) : [],
      smooth: true,
      showSymbol: false,
    })
  }
  return ret
})
const lineOption = computed(() => {
  return {
    legend: {
      show: false,
    },
    tooltip: {
      ...DEFAULT_OPTION.tooltip,
      ...tooltipTheme,
    },
    xAxis: {
      type: 'category',
      data: data.value[0]?.slice?.(1) ?? [],
    },
    yAxis: {
      type: 'value',
      min(value: { min: number, max: number }) {
        // return value.min > 0 ? Math.round(value.min * 0.5) : Math.round(value.min * 2)
        return Math.round(value.min - (value.max - value.min) / 20)
      },
      max(value: { min: number, max: number }) {
        // return value.max > 0 ? Math.round(value.max * 1.5) : Math.round(value.max / 1.5)
        return Math.round(value.max + Math.random() * 2)
      },
    },
    grid: {
      top: '40px',
      left: '20px',
      right: '80px',
      bottom: '60px',
      containLabel: true,
    },
    toolbox: {
      show: true,
      feature: {
        dataView: unref(dataView),
        magicType: {
          type: ['line', 'bar'],
          title: {
            line: '切换为折线图',
            bar: '切换为柱状图',
          },
        },
      },
    },
    dataZoom: [
      { type: 'slider', left: '120px', right: '120px', xAxisIndex: [0] },
      { type: 'slider', top: '60px', bottom: '60px', yAxisIndex: [0] },
      { type: 'inside' },
    ],
    series: series.value,
  }
})

const current = shallowRef<any>({
  indicatorNumber: props.indicatorNumber,
  indicatorName: '',
  unit: '',
  indicatorCode: '',
  time: '',
  value: null,
})

function format(v: string) {
  return dayjs(v).format(
    unref(isLive)
      ? 'YYYY-MM-DD HH:mm:00'
      : unref(pickerFormat),
  )
}

async function clickSearch() {
  if (new Date(unref(startTime)).getTime() > new Date(unref(endTime)).getTime())
    return ElMessage.error('结束时间不能小于开始时间')

  await queryIndicatorDataByTimeType({
    timeType: timeType.value,
    indicatorNumber: props.indicatorNumber,
    startTime: format(startTime.value),
    endTime: format(endTime.value),
    showYoy: showYoy.value,
    showMom: showMom.value,
  })
}

async function clickChart(e: any) {
  if (unref(timeType) !== STORAGE_MODES.NOW)
    return
  const [time, value] = e.data ?? []
  if (time) {
    current.value = {
      ...unref(indicator),
      time,
      value,
    }
    await nextTick()
    updateDataModalRef.value?.open()
  }
}

async function showModal() {
  timeType.value = props.initialTimeType
  startTime.value = props.initialStartTime
  endTime.value = props.initialEndTime
  await nextTick()
  clickSearch()
  setVisible(true)
}

// 时间从日切换到小时，格式化有bug 如 2023-10-01 不能正常显示 2023-10-01 00
watch(
  () => unref(timeType),
  (val: STORAGE_MODES) => {
    if (startCacheTime.value) {
      startTime.value = dayjs(unref(startCacheTime)).format(pickerFormat.value)
    }
    else {
      startTime.value = getDefaultTimes(val)?.initialStartTime ?? ''
      startCacheTime.value = startTime.value
    }
    if (endCacheTime.value) {
      endTime.value = dayjs(unref(endCacheTime)).format(pickerFormat.value)
    }
    else {
      endTime.value = getDefaultTimes(val)?.initialEndTime ?? ''
      endCacheTime.value = endTime.value
    }
  },
)

watch(
  () => unref(visible),
  (val: boolean) => {
    if (!val) {
      emits('close')
    }
  },
)

watch(
  [() => unref(showYoy), () => unref(showMom)],
  () => {
    if (yoyData.value.length === 0 || momData.value.length === 0) {
      clickSearch()
    }
  },
)

defineExpose({
  showModal,
})
</script>

<template>
  <FullscreenModal v-model="visible">
    <div v-if="visible" class="h-full w-full flex flex-col gap-4 p-4">
      <ElPageHeader class="flex-shrink-0" title="返回" @back="visible = false">
        <template #content>
          <span>{{ title }}</span>
        </template>
      </ElPageHeader>
      <ElForm class="flex-shrink-0" inline>
        <ElFormItem v-if="!isLive" label="时间类型">
          <ElSelect v-model="timeType">
            <ElOption
              v-for="item in timeTypeOptions"
              :key="item.value" :label="item.label" :value="item.value"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="时间">
          <ElDatePicker
            v-model="startTime"
            :popper-class="isHour ? 'is-hour-in-hide-panel' : ''"
            :type="pickerType"
            :format="pickerFormat"
            :value-format="pickerFormat"
            :clearable="false"
          />
          <span class="fs-14 text-placeholder mx-3">至</span>
          <ElDatePicker
            v-model="endTime"
            :popper-class="isHour ? 'is-hour-in-hide-panel' : ''"
            :type="pickerType"
            :format="pickerFormat"
            :value-format="pickerFormat"
            :clearable="false"
          />
        </ElFormItem>
        <ElFormItem v-if="showYoyOrMom && !isLive">
          <ElCheckbox v-model="showYoy">
            同比
          </ElCheckbox>
          <ElCheckbox v-model="showMom">
            环比
          </ElCheckbox>
        </ElFormItem>
        <ElFormItem class="ml-4">
          <SearchButton @click="clickSearch" />
        </ElFormItem>
      </ElForm>
      <div class="fs-14 text-regular flex flex-wrap items-center line-height-normal">
        <span class="text-placeholder">指标编码：</span> <code>{{ indicator.indicatorNumber }}</code>
        <span class="text-placeholder ml-10">指标名称：</span> {{ indicator.indicatorName }}
        <span class="text-placeholder ml-10">单位：</span> {{ indicator.unit }}
        <span class="text-placeholder ml-10">测点点位号：</span> <code>{{ indicator.indicatorCode }}</code>
      </div>
      <div v-loading="loading" element-loading-custom-class="global-loading" class="flex-1 overflow-auto p-4">
        <BChart
          autoresize
          :option="lineOption"
          @click="clickChart"
        />
      </div>
      <!-- 修改实时数据对话框 -->
      <UpdateDataModal
        v-if="current && current.time"
        ref="updateDataModalRef"
        v-model="current"
        @save-success="clickSearch"
      />
    </div>
  </FullscreenModal>
</template>

<style lang="scss">
.is-hour-in-hide-panel {
  .el-time-panel {
    .el-time-spinner__wrapper {
      width: 100%;
      &:last-child {
        display: none;
      }
    }
  }
}
</style>
